/**
 * @author Chris Lewis Nov 8, 2007 <chris@thegodcode.net>
 * @version $Id: slideshow.js 80 2007-12-28 20:36:08Z burningodzilla $
 */

/* 
 * Slide transitions are responsible for managing the effect
 * and action of changing the current slide in the slideshow.
 * A transition is just an object with a single method:
 *
 *     transition(from, to)
 *
 * This method takes two arguments: 'from' and 'to'. These
 * are references to the slide being moved out of view (from)
 * and the one being moved into view (to).
 * It is possible that the 'from' will be null. When this
 * happens it means that the slide show is just starting
 * and no slides have yet been rendered.
 *
 */
var SlideShow = Class.create();

/* A few customizable transitions. */
SlideShow.Txs = {};
SlideShow.Txs.Crossfade = Class.create();
SlideShow.Txs.Crossfade.prototype = {
	initialize: function(opts) {
		this.opts = opts;
	},
	
	transition: function(from, to) {
		if(from != null) {
			Effect.Fade(from, this.opts);
		}
		Effect.Appear(to, this.opts);
	}
}

SlideShow.Txs.Grow = Class.create();
SlideShow.Txs.Grow.prototype = {
	initialize: function(opts) {
		this.opts = opts;
	},
	
	transition: function(from, to) {
		if(from != null) {
			Effect.Shrink(from, this.opts);
		}
		Effect.Grow(to, this.opts);
	}
}

/* Prebuilt transitions for easy use. */
SlideShow.Tx = {};
SlideShow.Tx.Crossfade = new SlideShow.Txs.Crossfade({ duration: 1 });
SlideShow.Tx.Grow = new SlideShow.Txs.Grow({ duration: 1 });
SlideShow.Tx.Abrupt = {
	transition: function(from, to) {
		if(from != null) {
			from.hide();
		}
		to.show();
	}
}


SlideShow.prototype = {
	
	/**
	 * Resulting state for 'this':
	 * slides - slide collection (html elements)
	 * interval - the interval for cycling slides
	 * loop - flag showing if the show will loop
	 * pauseOnHover - flag showing if slide cycling should pause when the user is hovering
	 * slideIndex - current slide index
	 * tx - object providing the slide transition
	 * pe - PeriodicalExecuter timing the slide changes
	 *
	 * @param e The DOM id of the slideshow parent element.
	 * @param options Transfer object with slideshow configurations.
	 */
	initialize: function(e, options) {
		//gc-slideshow-slides
		this.slides = $(e).firstDescendant().childElements();
		this.slides.each(
			function(_slide) {
				_slide.hide().addClassName('gc-slide');
			}
		);
		this.slideIndex = 0;
		this.loop = options.loop;
		this.interval = options.interval;
		this.pauseOnHover = options.pauseOnHover;
		
		if(this.pauseOnHover) {
			Event.observe($(e), 'mouseover', this.pause.bind(this));
			Event.observe($(e), 'mouseout', this.play.bind(this));
		}
		
		// This is a reference to an object as a string, so we must eval().
		this.tx = eval(options.transition);
		// Fire this here so the first slide renders immediately.
		this.tx.transition(null, this.slides[0]);
		
		this.play();
	},
	
	play: function() {
		this.pe = new PeriodicalExecuter(this.next.bind(this), this.interval);
	},
	
	pause: function() {
		this.pe.stop();
	},
	
	next: function() {
		var _currentSlide = this.slides[this.slideIndex];
		if(++this.slideIndex == this.slides.size()) {
			if(! this.loop) {
				this.pe.stop();
				return;
			} else {
				this.slideIndex = 0;
			}
		}
		var _nextSlide = this.slides[this.slideIndex];
		this.tx.transition(_currentSlide, _nextSlide);
	}
	
}